#####################################################################
# Product:      KnowledgeEngine (Plone Edition)
#
# File:         MultiSelectionEditlet.py
#
# Copyright:    Copyright (c) 2004, Faulkner Technologies
#
# Author:       Brian Oliver
#
# Description:  This file defines the MultiSelectionEditlet class, that is
#               used to generate widgets that permit multiple selections
#               of values from enumerated types
#
# See Also:     PropertyEditlet, PropertyRefleciton, 
#               PropertyDefinition, PropertyAccess 
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Products.KnowledgeEngine.Common import *
from Products.KnowledgeEngine.Core import *
from Products.KnowledgeEngine.Editlet import Editlet
from Products.KnowledgeEngine.PropertyTypes import *
from Products.KnowledgeEngine.PropertyFormats import *
from Products.KnowledgeEngine.PropertyStructures import *

#####################################################################
## Zope Library Imports
# (none)
 
#####################################################################
## Python Library Imports
import string
import types

#####################################################################
## MultiSelectionEditlet Class Definition
class MultiSelectionEditlet(Editlet):
    """
        An editlet for editing enumerated types
    """
    
    #---------------------------------------------------------------#

    def displayNameFor(self, value, possibleValues):
        """
            Returns the displayName for the specified value
            from the specified possible values.
        """
        
        for (displayName, displayValue) in possibleValues:
            if displayValue == value:
                return displayValue
               
        raise "Missing Value Exception", "MultiSelectionEditlet can't locate display name for value %s in %s" % (value, possibleValues)
    
    #---------------------------------------------------------------#
    
    def isEditable(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """
            Returns if the specified propertyDefinition can be
            edited by this editlet
        """

        return propertyDefinition.getStructure() == ps_LIST and propertyDefinition.hasEnumeratedValues()
        
    #---------------------------------------------------------------#

    def generateEditorFor(self, propertyDefinition, propertyAccess=None, value=None, isForConstructor=false, REQUEST=None, context=None):
        """
            Returns a HTML editlet for the specified property.
        """

        #get the enumerated values [(DisplayName,Value)] from the property definition class (one must be provided)
        possibleValues = propertyDefinition.getEnumeratedValues(context)
                
        #the resulting editlet
        result = ""

        #-----------------
        #is the property read only?        
        if propertyDefinition.isReadPermitted() and not propertyDefinition.isWritePermitted():

            #get the value for the property
            if isForConstructor:
                value = propertyDefinition.getDefaultValue()
            else:
                value = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())
            
            #create the editor
            result = "<table border=1><tr><td>%s</td></tr></table>" % (self.displayNameFor(value,possibleValues),)
        
        #-----------------
        #is the property writable?
        if propertyDefinition.isWritePermitted():
       
            #get the value for the property
            if propertyDefinition.isReadPermitted():
                if isForConstructor:
                    value = propertyDefinition.getDefaultValue()
                else:
                    #get the value for the property
                    value = propertyAccess.getPropertyValue(propertyDefinition.getIdentity())
            else:
                #not readable
                value = []
                
            #create the editor            
            for (displayName, displayValue) in possibleValues:
            
                #determine if the item is already selected
                if propertyDefinition.isReadPermitted() and (displayValue in value):
                    selected = "checked"
                else:
                    selected = ""                    
            
                #output a line break between items
                if len(result) > 0:
                    result += "<br>"

                #ensure our value doesn't get weirdly cast into a string!
                if propertyDefinition.getType() == pt_LONG or propertyDefinition.getType() == pt_INTEGER:
                    format = "%d"
                elif propertyDefinition.getType() == pt_FLOAT: 
                    format = "%f"
                else:          
                    format = "%s"
                    
                #output a checkbox
                result += ("<input type='checkbox' id=\"%s\" name='kems%s' value='" + format + "' %s> %s") % (propertyDefinition.getIdentity(), propertyDefinition.getIdentity(), displayValue, selected, displayName)
                                    
        return result
        
    #---------------------------------------------------------------#

    def updatePropertyWith(self, propertyDefinition, propertyAccess, REQUEST=None):
        """
            Attempts to update the specified property on the
            object implementing the PropertyAccess interface with the
            specified HTTP REQUEST.
        """
        
        #is write permitted on the specified property?
        if propertyDefinition.isWritePermitted():
        
            #rebuild the entire list from the selections
            #(remember when checkboxes aren't selected, values aren't submitted)
            key = 'kems%s' % propertyDefinition.getIdentity()
            
            #has anything been selected?
            if not REQUEST.has_key(key):
                value = []
            else:
                value = REQUEST[key]

                #ensure the value is a list (value will be a string if only one item is selected)
                if not type(value) is types.ListType:
                    value = [value]

            # Check we have a value if it isMandatory
            propertyDefinition.verifyMandatoryValue(value)
            
            #set the value for the property
            propertyAccess.setPropertyValue(propertyDefinition.getIdentity(), value)        
        
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation

# Register Editlet Information with the Knowledge Engine
registerEditlet("MultiSelectionEditlet", MultiSelectionEditlet())

#####################################################################
